package cn.le.javaNet;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * 用户数据报协议（UDP）
 * 它并不刻意的最球数据包完全会发送出去，也不能担保它们抵达的顺序与它们发出的顺序是一样的，
 *  可以认为这是一种不可靠的协议，但是它的速度很快
 *
 *  网游传输声音可用，报时服务
 *
 *  DatagramSocket（数据报套接字），UDP不需要等待建立一个链接，这是由于不再存在“链接”，
 *  取而代之的是一个数据报陈列出来，ServerSocket建立链接就不再关心谁向谁“说话”，
 *  只需要会话流回传数据即可，但是对于数据报来说，它的数据必须知道自己来自那里，以及打算去那里，
 *  否则信息就不能正常的发送。
 *
 *  DatagramSocket用于收发数据报，而DatagramPacket包含了具体的信息，准备接受一个
 *  数据报时，只需要提供一个缓冲区，以便安置接受到的数据，数据包抵达时，通过DatagramSocket
 *  作为信息起源地的因特网地址以及端口编号会自动的到初始化，所有一个用于接收数据报的
 *  DatagramPacket构造器是DategramPacket（buf,buf.length）
 *  可影重复使用数据报的接收代码，不必每次都建一个新的，每次用它的时候，缓冲区内的数据都会被覆盖。
 *
 *  换从前的最大容量受限于允许的数据包大小
 *
 *
 */
public class Dgram {

    /**
     * 构造DatagramPacket
     * @param s
     * @param destIA
     * @param destPort
     * @return
     */
    public static DatagramPacket toDatagram(String s, InetAddress destIA,
                                            int destPort)
    {
        byte[] buf = new byte[s.length()+1];
        //把s中的信息填充到buf中
        s.getBytes(0,s.length(),buf,0);

        return new DatagramPacket(buf,buf.length,destIA,destPort);
    }
    //获取DatagramPacket中的数据
    public static String toString(DatagramPacket p)
    {
        return new String(p.getData(),0,p.getLength());
    }
}

/**
 * 数据报服务器
 */
class ChatterServer{

    static final int inport = 1711;
    private byte[] buf = new byte[100000];
    //构造 DatagramPacket，用来接收长度为 length 的数据包。
    private DatagramPacket dp = new DatagramPacket(buf,buf.length);

    private DatagramSocket socket;

    private ChatterServer()
    {
        try {
            //创建一个数据报套接字，并绑定到1711端口
            socket = new DatagramSocket(inport);
            System.out.println("Server started");

            while(true)
            {
                //从此数据报中接收数据，会暂时挂起(堵塞)
                socket.receive(dp);
                String rcvd = Dgram.toString(dp)
                        +", from address:"+dp.getAddress()
                        +", port:"+dp.getPort();

                System.out.println(rcvd);
                String echoString = "Echoed: "+rcvd;
                System.out.println("echoString:"+echoString);
                DatagramPacket echo = Dgram.toDatagram(echoString,
                        dp.getAddress(),dp.getPort());

                //从此数据报中发送数据，当数据报真正发送的时候才会把本机的地址和端口写入数据报
                System.out.println("发送"+Dgram.toString(echo));
                socket.send(echo);
            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {

        new ChatterServer();
    }


}

